package indi.zjh.dp.access;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpContent;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpHeaderValues;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpUtil;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.handler.codec.http.QueryStringDecoder;
import io.netty.handler.codec.http.multipart.DefaultHttpDataFactory;
import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder;
import io.netty.handler.codec.http.multipart.InterfaceHttpData;
import io.netty.handler.codec.http.multipart.InterfaceHttpData.HttpDataType;
import io.netty.handler.codec.http.multipart.MemoryAttribute;

public class HttpServerHandler extends ChannelInboundHandlerAdapter {
	private ByteBufToBytes reader;
	private HttpServer server;
	private HttpRequest request;
	
	public HttpServerHandler(HttpServer server)
	{
		this.server = server;
	}
	
	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception
	{
		Map<String, String> requestParams = new HashMap<>();
		String uri = null;
		
		if (msg instanceof HttpRequest) {
            this.request = (HttpRequest) msg;

            uri = request.uri();
            if (HttpUtil.isContentLengthSet(request)) {
            	int maxlength = (int)HttpUtil.getContentLength(request);
            	if(maxlength > 4096)
            	{
            		responseError(ctx, "error");
            		ctx.close();
            		return;
            	}
                reader = new ByteBufToBytes((int) HttpUtil.getContentLength(request));
            }
            if(request.method() == HttpMethod.GET)
            {
            	QueryStringDecoder decoder = new QueryStringDecoder(request.uri());
                Map<String, List<String>> parame = decoder.parameters();  
                Iterator<Map.Entry<String, List<String>>> iterator = parame.entrySet().iterator();
                while(iterator.hasNext()){
                    Map.Entry<String, List<String>> next = iterator.next();
                    requestParams.put(next.getKey(), next.getValue().get(0));
                }
            	
            	Router router = new Router();
            	Api api = router.getMappedApi(uri);
            	String responseContent = "";
            	if(api == null)
            	{
            		responseContent = "Not found";
            	}
            	else
            	{
            		ApiContext context = new ApiContext(this.server, requestParams, HttpMethod.GET);
            		api.process(context);
            		responseContent = context.getResponseContent();
            	}
            	
            	
        		FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.wrappedBuffer(responseContent.getBytes()));
        		response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html;charset=UTF-8");
        		response.headers().set(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());
        		response.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
        		ctx.write(response);
        		ctx.flush();

            }
            
        }
		

		
		
        if (msg instanceof HttpContent) {
            HttpContent httpContent = (HttpContent) msg;
            
            ByteBuf content = httpContent.content();
            reader.reading(content);
            content.release();
            if (reader.isEnd()) {
                String resultStr = new String(reader.readFull());

                QueryStringDecoder decoder = new QueryStringDecoder("/index.php?"+resultStr);  
                Map<String, List<String>> parame = decoder.parameters();  
                Iterator<Map.Entry<String, List<String>>> iterator = parame.entrySet().iterator();
                while(iterator.hasNext()){
                    Map.Entry<String, List<String>> next = iterator.next();
                    requestParams.put(next.getKey(), next.getValue().get(0));
                }
                
                Router router = new Router();
            	Api api = router.getMappedApi(this.request.uri());
            	String responseContent = "";
            	if(api == null)
            	{
            		responseContent = "Not found";
            	}
            	else
            	{
            		ApiContext context = new ApiContext(this.server, requestParams, HttpMethod.POST);
            		api.process(context);
            		responseContent = context.getResponseContent();
            	}
            	
                FullHttpResponse response = new DefaultFullHttpResponse(
                        HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.wrappedBuffer(responseContent
                                .getBytes()));
                response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain");
                response.headers().set(HttpHeaderNames.CONTENT_LENGTH,
                        response.content().readableBytes());
                response.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
                ctx.write(response);
                ctx.flush();
            }
        }
        
	}
	
	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception
	{
		ctx.flush();
	}
	
	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception
	{
		ctx.close();
	}
	
	private void responseError(ChannelHandlerContext ctx, String content)
	{
		FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.wrappedBuffer(content.getBytes()));
		response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain");
		response.headers().set(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());
		response.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.CLOSE);
		ctx.write(response);
		ctx.flush();
	}
}
